home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
raytrace
/
rayshade
/
graphtal.lzh
/
Graphtal.Amiga
/
ViewTransform.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-17
|
3KB
|
124 lines
/*
* ViewTransform.C - general view transformation.
*
* Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
* University of Berne, Switzerland
* All rights reserved.
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
*/
#include "ViewTransform.h"
#include "Error.h"
//___________________________________________________________ ViewTransform
ViewTransform::ViewTransform(const Vector& Eye, const Vector& Lookat,
const Vector& Up, real Fov, int ResX, int ResY)
: eye(Eye), lookat(Lookat), up(Up), fov(Fov), resX(ResX), resY(ResY)
{
buildView();
}
ViewTransform::ViewTransform(const BoundingBox& b, const Vector& Up, real Fov,
int ResX, int ResY)
: up(Up), fov(Fov), resX(ResX), resY(ResY)
{
real widthX2 = 0.5*(b.xmax()-b.xmin());
real widthY2 = 0.5*(b.ymax()-b.ymin());
real height2 = 0.5*(b.zmax()-b.zmin());
if (widthX2 > widthY2) {
// let's look to the xz-plane
if (widthX2 >= height2)
eye[1] = b.ymax() + widthX2/tan(dtor(fov/2));
else
eye[1] = b.ymax() + height2/tan(dtor(fov/2));
eye[0] = lookat[0] = b.xmin() + widthX2;
lookat[1] = b.ymax();
}
else {
// let's look to the yz-plane
if (widthY2 >= height2)
eye[0] = b.xmax() + widthY2/tan(dtor(fov/2));
else
eye[0] = b.xmax() + height2/tan(dtor(fov/2));
eye[1] = lookat[1] = b.ymin() + widthY2;
lookat[0] = b.xmax();
}
eye[2] = lookat[2] = b.zmin()+height2;
buildView();
}
Vector ViewTransform::transformWorld2Screen(const Vector& p)
{
Vector vp = p*viewmat;
if (equal(vp[2], 0))
return Vector(0,0,0);
real scale = widthOfViewplane/vp[2];
vp[0] = resX*(0.5+vp[0]*scale);
vp[1] = resY*(0.5+vp[1]*scale);
return vp;
}
Vector ViewTransform::transformWorld2View(const Vector& p)
{
return p*viewmat;
}
Vector ViewTransform::transformView2Screen(const Vector& p)
{
if (equal(p[2], 0))
return Vector(0,0,0);
Vector vp = p;
real scale = widthOfViewplane/vp[2];
vp[0] = resX*(0.5+vp[0]*scale);
vp[1] = resY*(0.5+vp[1]*scale);
return vp;
}
// buildView assumes that eye, lookat, up, fov, resX, resY are already set!!!
void ViewTransform::buildView()
{
Vector n,v,u;
n = lookat - eye; n.normalize();
v = up - (n^up)*n;
if (v.normalize() == 0)
Error(ERR_PANIC, "The view and up directions are identical?");
u = n * v;
widthOfViewplane = 0.5/(tan(dtor(fov)/2));
viewmat(0,0) = u[0]; viewmat(1,0) = u[1]; viewmat(2,0) = u[2];
viewmat(0,1) = v[0]; viewmat(1,1) = v[1]; viewmat(2,1) = v[2];
viewmat(0,2) = n[0]; viewmat(1,2) = n[1]; viewmat(2,2) = n[2];
viewmat(3,0) = -eye[0]*u[0] - eye[1]*u[1] - eye[2]*u[2];
viewmat(3,1) = -eye[0]*v[0] - eye[1]*v[1] - eye[2]*v[2];
viewmat(3,2) = -eye[0]*n[0] - eye[1]*n[1] - eye[2]*n[2];
}
ostream& operator<<(ostream& os, const ViewTransform& view)
{
os << "Eye: " << view.eye << '\n'
<< "Lookat: " << view.lookat << '\n'
<< "Up: " << view.up << '\n'
<< "Fov: " << view.fov << '\n';
return os;
}